using System.Collections.Concurrent;

namespace Traceability.API.Services
{
    /// <summary>
    /// 基于内存的验证码服务（备用方案）
    /// </summary>
    public class MemoryCaptchaService
    {
        private readonly CaptchaService _captchaService;
        private readonly ConcurrentDictionary<string, CaptchaInfo> _captchaStore;
        private readonly Timer _cleanupTimer;
        
        // 验证码默认过期时间（5分钟）
        private const int DefaultExpireSeconds = 300;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="captchaService">验证码服务</param>
        public MemoryCaptchaService(CaptchaService captchaService)
        {
            _captchaService = captchaService;
            _captchaStore = new ConcurrentDictionary<string, CaptchaInfo>();
            
            // 每分钟清理一次过期的验证码
            _cleanupTimer = new Timer(CleanupExpiredCaptchas, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
        }

        /// <summary>
        /// 生成验证码并存储到内存
        /// </summary>
        /// <param name="length">验证码长度</param>
        /// <param name="width">图片宽度</param>
        /// <param name="height">图片高度</param>
        /// <param name="expireSeconds">过期时间（秒）</param>
        /// <returns>验证码信息（ID、图片、过期时间）</returns>
        public async Task<(string CaptchaId, byte[] ImageBytes, DateTime ExpireTime)> GenerateCaptchaAsync(
            int length = 4, 
            int width = 120, 
            int height = 40, 
            int expireSeconds = DefaultExpireSeconds)
        {
            // 生成随机验证码
            string code = _captchaService.GenerateRandomCode(length);
            
            // 生成唯一ID
            string captchaId = $"captcha_{Guid.NewGuid():N}";
            
            // 计算过期时间
            DateTime expireTime = DateTime.Now.AddSeconds(expireSeconds);
            
            // 生成验证码图片
            byte[] imageBytes = _captchaService.GenerateCaptchaImage(code, width, height);
            
            // 存储验证码到内存
            var captchaInfo = new CaptchaInfo
            {
                Code = code,
                ExpireTime = expireTime
            };
            
            _captchaStore.TryAdd(captchaId, captchaInfo);
            
            return await Task.FromResult((captchaId, imageBytes, expireTime));
        }

        /// <summary>
        /// 验证验证码
        /// </summary>
        /// <param name="captchaId">验证码ID</param>
        /// <param name="inputCode">用户输入的验证码</param>
        /// <returns>验证结果</returns>
        public async Task<bool> ValidateCaptchaAsync(string captchaId, string inputCode)
        {
            if (string.IsNullOrEmpty(captchaId) || string.IsNullOrEmpty(inputCode))
            {
                return false;
            }
            
            // 从内存获取验证码
            if (!_captchaStore.TryGetValue(captchaId, out var captchaInfo))
            {
                return false;
            }
            
            // 检查是否过期
            if (DateTime.Now > captchaInfo.ExpireTime)
            {
                _captchaStore.TryRemove(captchaId, out _);
                return false;
            }
            
            // 验证验证码
            bool isValid = string.Equals(inputCode, captchaInfo.Code, StringComparison.OrdinalIgnoreCase);
            
            // 验证成功后删除验证码（一次性使用）
            if (isValid)
            {
                _captchaStore.TryRemove(captchaId, out _);
            }
            
            return await Task.FromResult(isValid);
        }

        /// <summary>
        /// 清理过期的验证码
        /// </summary>
        /// <param name="state">状态</param>
        private void CleanupExpiredCaptchas(object state)
        {
            var now = DateTime.Now;
            var expiredKeys = _captchaStore
                .Where(kvp => now > kvp.Value.ExpireTime)
                .Select(kvp => kvp.Key)
                .ToList();

            foreach (var key in expiredKeys)
            {
                _captchaStore.TryRemove(key, out _);
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _cleanupTimer?.Dispose();
        }

        /// <summary>
        /// 验证码信息
        /// </summary>
        private class CaptchaInfo
        {
            public string Code { get; set; }
            public DateTime ExpireTime { get; set; }
        }
    }
}
